package com.idealighter.game.games.errenniuniu.manager;

import com.google.inject.Inject;
import com.google.inject.Singleton;

import com.idealighter.game.dictionary.dic.ErrenniuniuRoomDic;
import com.idealighter.game.dictionary.dic.ErrenniuniuRoomTypeDic;
import com.idealighter.game.dictionary.domain.ErrenniuniuRoomDomain;
import com.idealighter.game.gamehall.dto.MemInfo;
import com.idealighter.game.games.common.AbstractRoom;
import com.idealighter.game.games.common.AbstractTable;
import com.idealighter.game.games.common.RoomState;
import com.idealighter.game.games.common.niuniu.NiuNiuCard;
import com.idealighter.game.games.errenniuniu.dto.RoomInfo;
import com.idealighter.game.games.errenniuniu.dto.RoomTypeDetailInfo;
import com.idealighter.game.games.errenniuniu.message.ResBetMsg;
import com.idealighter.game.games.errenniuniu.message.ResCallDealerMsg;
import com.idealighter.game.games.errenniuniu.message.ResChipsChangeMsg;
import com.idealighter.game.games.errenniuniu.message.ResDealCardsMsg;
import com.idealighter.game.games.errenniuniu.message.ResEnterGameHallMsg;
import com.idealighter.game.games.errenniuniu.message.ResEnterRoomMsg;
import com.idealighter.game.games.errenniuniu.message.ResEnterTableMsg;
import com.idealighter.game.games.errenniuniu.message.ResExchangeTableMsg;
import com.idealighter.game.games.errenniuniu.message.ResExitRoomMsg;
import com.idealighter.game.games.errenniuniu.message.ResExitTableMsg;
import com.idealighter.game.games.errenniuniu.message.ResFastEnterTableMsg;
import com.idealighter.game.games.errenniuniu.message.ResGameOverMsg;
import com.idealighter.game.games.errenniuniu.message.ResOtherEnterTableMsg;
import com.idealighter.game.games.errenniuniu.message.ResReadyMsg;
import com.idealighter.game.games.errenniuniu.message.ResShowdownMsg;
import com.idealighter.game.games.errenniuniu.struct.ErRenNiuNiuRoom;
import com.idealighter.game.games.errenniuniu.struct.ErRenNiuNiuSeat;
import com.idealighter.game.games.errenniuniu.struct.ErRenNiuNiuTable;
import com.idealighter.game.message.core.ResMessage;
import com.idealighter.game.player.manager.PlayerMsgWriter;
import com.idealighter.game.player.struct.Player;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 二人牛牛消息管理 .
 * 
 * @date 2015年9月15日 下午7:41:51
 *
 */
@Singleton
public class ErRenNiuNiuMsgMgr {

  @Inject
  private PlayerMsgWriter msgWriter;
  @Inject
  private ErRenNiuNiuDataMgr dataMgr;
  @Inject
  private ErrenniuniuRoomDic roomDic;
  @Inject
  private ErrenniuniuRoomTypeDic roomTypeDic;

  /**
   * 发送房间数据 .
   * 
   * @param player 玩家.
   */
  public void sendEnterGameHallMsg(Player player) {
    ResEnterGameHallMsg msg = new ResEnterGameHallMsg();

    Collection<ErRenNiuNiuRoom> rooms = dataMgr.rooms();
    for (ErRenNiuNiuRoom room : rooms) {
      ErrenniuniuRoomDomain roomDom = roomDic.map().get(room.getId().intValue());
      if (roomDom.getIsActive() != 1) {
        continue;
      }
      RoomTypeDetailInfo roomTypeDetailInfo = new RoomTypeDetailInfo();

      roomTypeDetailInfo.setType(roomDom.getType());
      roomTypeDetailInfo.setTypeName(roomTypeDic.map().get(roomDom.getType()).getName());

      RoomInfo roomInfo = new RoomInfo();
      roomInfo.setRoomId(room.getId().intValue());
      roomInfo.setName(roomDom.getName());
      roomInfo.setType(roomDom.getType());
      roomInfo.setMaxNum(roomDom.getMaxNum());
      roomInfo.setFree(roomDom.getFree());
      roomInfo.setGeneral(roomDom.getGeneral());
      roomInfo.setCrowded(roomDom.getCrowded());
      roomInfo.setLower(roomDom.getLower());
      roomInfo.setUpper(roomDom.getUpper());
      roomInfo.setProportionGold(roomDom.getProportionGold());
      roomInfo.setProportionChips(roomDom.getProportionChips());
      roomInfo.setTabble(roomDom.getTable());
      roomInfo.setMaxOne(roomDom.getMaxOne());
      roomInfo.setMinOne(roomDom.getMinOne());
      roomInfo.setAfee(roomDom.getAfee());
      roomInfo.setInType(roomDom.getInType());
      roomInfo.setPlayerNum(room.getPlayers().size());
      roomInfo.setStatus(roomStatus(room).desc);
      roomInfo.setDisplayNames(roomDom.getDisplays());
      roomInfo.setPlaceHolder(roomDom.getPlaceHolder());
      roomTypeDetailInfo.getRooms().add(roomInfo);

      msg.getRoomTypes().add(roomTypeDetailInfo);
    }

    msgWriter.writeMsg(player, msg);
  }

  /**
   * 房间状态，空闲,普通,拥挤,爆满 .
   * 
   * @param room .
   * @return
   */
  private RoomState roomStatus(ErRenNiuNiuRoom room) {
    int playersNum = room.getPlayers().size();
    ErrenniuniuRoomDomain roomDom = roomDic.map().get(room.getId().intValue());

    if (playersNum < roomDom.getMaxNum() * roomDom.getFree() / 100) {
      return RoomState.IDLE;
    } else if (playersNum < roomDom.getMaxNum() * roomDom.getGeneral() / 100) {
      return RoomState.GENERAL;
    } else if (playersNum < roomDom.getMaxNum() * roomDom.getCrowded() / 100) {
      return RoomState.CROWD;
    } else {
      return RoomState.FULL;
    }

  }

  /**
   * 发送兑换筹码消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendChipsChangeMsg(ErRenNiuNiuSeat seat) {
    ResChipsChangeMsg msg = new ResChipsChangeMsg();
    msg.setChips(seat.getTotalChips());
    msg.setPlayerId(seat.getPlayerId());
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送进入桌子消息 .
   * 
   * @param player 玩家.
   */
  public void sendEnterRoomMsg(Player player) {
    ResEnterRoomMsg msg = new ResEnterRoomMsg();
    for (AbstractTable table : player.curRoom.tables()) {
      msg.getTables().add(table.tableInfo());
    }
    msg.setMembers(player.curRoom.memInfos());
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发送进入桌子消息 .
   * 
   * @param player 玩家.
   * @param table .
   */
  public void sendEnterTableMsg(Player player, AbstractTable table) {
    ResEnterTableMsg msg = new ResEnterTableMsg();
    AbstractRoom room = table.room();
    List<MemInfo> mems = new ArrayList<>();
    for (Long playerId : table.players()) {
      mems.add(room.memInfo(playerId));
    }
    msg.setMems(mems);

    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发送退出房间消息 .
   * 
   * @param player 玩家.
   * @param res 0:退出成功,1:在牌桌中退出失败 .
   */
  public void sendExitRoomMsg(Player player, int res) {
    ResExitRoomMsg msg = new ResExitRoomMsg();
    msg.setRes(res);
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 向同桌的玩家发送该座位的玩家已经准备好 .
   * 
   * @param seat 座位信息.
   * @param res 0:成功,1:重复准备 .
   */
  public void sendReadyMsg(ErRenNiuNiuSeat seat, int res) {
    ResReadyMsg msg = new ResReadyMsg();
    msg.setPlayerId(seat.getPlayerId());
    msg.setCallPlayerId(seat.table.nextCallPlayer);
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发牌 .
   * 
   * @param seat 座位信息.
   */
  public void sendDealCardsMsg(ErRenNiuNiuSeat seat) {
    ResDealCardsMsg msg = new ResDealCardsMsg();
    for (NiuNiuCard card : seat.cards) {
      msg.getCards().add(card.ordinal());
    }
    msg.setCardsType(seat.cardsType.niu);
    for (NiuNiuCard card : seat.bestCards) {
      msg.getTipCards().add(card.ordinal());
    }
    msg.setChips(seat.billChips);
    msgWriter.writeMsg(seat.getPlayerId(), msg);
  }

  /**
   * 发送交换牌桌位置消息 .
   * 
   * @param player 玩家.
   * @param res 0:成功,1:已经准备不能交换桌子,2:当前房间没有空位置 .
   */
  public void sendExchangeTableMsg(Player player, int res) {
    ResExchangeTableMsg msg = new ResExchangeTableMsg();
    msg.setRes(res);
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发送退出桌子消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendExitTableMsg(ErRenNiuNiuSeat seat) {
    ResExitTableMsg msg = new ResExitTableMsg();
    msg.setPlayerId(seat.getPlayerId());
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送座位叫庄消息 .
   * 
   * @param seat 座位信息.
   * @param callType . 0:不叫,非0:叫 .
   */
  public void sendCallDealerMsg(ErRenNiuNiuSeat seat, int callType) {
    ResCallDealerMsg msg = new ResCallDealerMsg();
    ErRenNiuNiuSeat dealer = seat.table.dealer();

    msg.setPlayerId(seat.getPlayerId());
    msg.setOrder(seat.getOrder());
    msg.setDealer(dealer == null ? 0 : dealer.getPlayerId());
    msg.setCallType(callType);
    msg.setNextCallPlayer(seat.table.nextCallPlayer);
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送下注结果消息 .
   * 
   * @param seat 座位信息.
   * @param res 0:成功,1:筹码不合法 .
   */
  public void sendBetMsg(ErRenNiuNiuSeat seat, int res) {
    ResBetMsg msg = new ResBetMsg();
    msg.setRes(res);
    if (res != 0) {
      msgWriter.writeMsg(seat.getPlayerId(), msg);
    } else {
      msg.setChips(seat.betedchips);
      sendTablePlayersMsg(seat.table, msg);
    }
  }

  /**
   * 发送座位摊牌消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendShowdownMsg(ErRenNiuNiuSeat seat) {
    ResShowdownMsg msg = new ResShowdownMsg();
    msg.setPlayerId(seat.getPlayerId());
    seat.bestCards.forEach(card -> msg.getBestCards().add(card.ordinal()));
    msg.setCardsType(seat.cardsType.niu);
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送其他人进入桌子消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendOtherEnterTableMsg(ErRenNiuNiuSeat seat) {
    ResOtherEnterTableMsg msg = new ResOtherEnterTableMsg();
    msg.setMem(seat.table.room.memInfo(seat.getPlayerId()));
    for (Long playerId : seat.table.players()) {
      if (playerId != seat.getPlayerId()) {
        msgWriter.writeMsg(playerId, msg);
      }
    }
  }

  /**
   * 向牌中的玩家发送游戏结束消息(结算信息已经在发牌信息中发送了) .
   * 
   * @param table .
   */
  public void sendGameOver(ErRenNiuNiuTable table) {
    ResGameOverMsg msg = new ResGameOverMsg();
    sendTablePlayersMsg(table, msg);
  }

  /**
   * 发送快速进入结果消息 .
   * 
   * @param player 玩家.
   * @param res 0:成功,1:没有空位置 .
   */
  public void sendFastEnterTableMsg(Player player, int res) {
    ResFastEnterTableMsg msg = new ResFastEnterTableMsg();
    msg.setRes(res);
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 向同桌的玩家(包括自己)发送消息 .
   * 
   * @param table .
   * @param msg .
   */
  public void sendTablePlayersMsg(ErRenNiuNiuTable table, ResMessage msg) {
    msgWriter.writeMsg(table.seat1.getPlayerId(), msg);
    msgWriter.writeMsg(table.seat2.getPlayerId(), msg);
  }

  /**
   * 向同房间的玩家(包括自己)发送消息 .
   * 
   * @param room .
   * @param msg .
   */
  public void sendRoomPlayersMsg(ErRenNiuNiuRoom room, ResMessage msg) {
    room.getPlayers().forEach(p -> msgWriter.writeMsg(p, msg));
  }
}
